/* tcpackit.c - tcpackit */

#include "tcpfms.h"
#include "ether.h"
#include "tcb.h"

/*------------------------------------------------------------------------
 *  tcpackit -  generate an ACK for a received TCP packet
 *------------------------------------------------------------------------
 */
int tcpackit(struct tcb *ptcb, struct udp *pudpin)
{
    struct udp  *pudpout;
    struct tcp	*ptcpin = (struct tcp *)pudpin->udp_data, *ptcpout;

    if (ptcpin->tcp_code & TCPF_RST)
        return OK;
    //if (pipin->ip_len <= IP_HLEN(pipin) + TCP_HLEN(ptcpin) &&
    //            !(ptcpin->tcp_code & (TCPF_SYN|TCPF_FIN)))
    if (pudpin->udp_len <= TCP_HLEN(ptcpin) &&
                !(ptcpin->tcp_code & (TCPF_SYN|TCPF_FIN)))
            return OK;	// duplicate ACK
    
    pudpout = (struct udp *)malloc(sizeof(struct udp));
    ptcpout = (struct tcp *)(pudpout->udp_data);
    if (ptcpout == NULL)
            return SYSERR;
    //pepout->ep_order = ~0;
    //pipout = (struct ip *)pepout->ep_data;
    pudpout->ip_src = pudpin->ip_dst;
    pudpout->ip_dst = pudpin->ip_src;
    ptcpout = (struct tcp *)pudpout->udp_data;
    ptcpout->tcp_sport = ptcpin->tcp_dport;
    ptcpout->tcp_dport = ptcpin->tcp_sport;
    ptcpout->tcp_seq = ptcb->tcb_snext;
    ptcpout->tcp_ack = ptcb->tcb_rnext;
    ptcpout->tcp_code = TCPF_ACK;
    ptcpout->tcp_offset = TCPHOFFSET;
    ptcpout->tcp_window = tcprwindow(ptcb);
    ptcpout->tcp_urgptr = 0;
    ptcpout->tcp_cksum = 0;
    tcph2net(ptcpout);
    //pepout->ep_order &= ~EPO_TCP;
    ptcpout->tcp_cksum = tcpcksum(pudpout, TCPMHLEN);
    TcpOutSegs++;
    return udpsend(pudpin->ip_src, ptcpout->tcp_dport, ptcpout, sizeof(struct tcp));
    //return ipsend(pipin->ip_src, pepout, TCPMHLEN, IPT_TCP,
    //        IPP_NORMAL, IP_TTL);
}
